#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>

uint32_t sram_code_arctan( int addr );
uint32_t sram_code_arctan_44s( int addr );
uint32_t sram_code_exp( int addr );

int main(){
    int addr = 0;
    
    for( addr = 0; addr <4096; addr++ ){
        int val1 = sram_code_arctan(addr);
        int val2 = sram_code_arctan_44s(addr);
        int val3 = sram_code_exp(addr);
        printf("%10d %10d %10d\n", val1, val2, val3);
    }
    
    return 0;
}

//  借助arctan函数平滑行转移驱动时序
uint32_t sram_code_arctan( int addr ){

    uint32_t addr_offset = 100*0;
    uint32_t addr0 = 0x000;
    uint32_t addr1 = 0x400;
    uint32_t addr2 = 0x800;
    uint32_t addr3 = 0xc00;
    
    uint32_t code;
/*    uint32_t code_max = 600;*/
    uint32_t code_max = 575;

    double slope = 0.5;
    // double slope = 1;       // default
    // double slope = 2;
    double pi = 3.14159;
    double pi_2 = pi/2;
    
    double tmp;
    
    int addrx = addr;

//  A4/D4
    if( addrx >= addr0 && addr < addr1 ){
    
        if( addrx >= addr0 + 900 + addr_offset ){
            tmp = 0;
        } else {
        
            int addr_tmp = addr;
            if( addr_tmp < 300 ){
                tmp = code_max * ( pi_2 + atan(slope*(addr_tmp-100)) );
            } else {
                tmp = code_max * ( pi_2 - atan(slope*(addr_tmp-500)) );
            }
        }
    }

//  A3/D3
    if( addrx >= addr1 && addr < addr2 ) {
        
        if( addrx >= addr1 + 900 + addr_offset ){
            tmp = 0;
        } else {
            int addr_tmp = addr - 1024;
            if( addr_tmp < 500 ){
                tmp = code_max * ( pi_2 + atan(slope*(addr_tmp-300)) );
            } else {
                tmp = code_max * ( pi_2 - atan(slope*(addr_tmp-700)) );
            }
        }
    }


//  A2/D2
    if( addrx >= addr2 && addr < addr3 ) {
    
        if( addrx >= addr2 + 900 + addr_offset ){
            tmp = 0;
        } else {
            int addr_tmp = addr - 1024*2;
            if( addr_tmp < 300 ){
                tmp = code_max * ( pi_2 + atan(slope*(addr_tmp-100)) );
            } else {
                tmp = code_max * ( pi_2 - atan(slope*(addr_tmp-500)) );
            }
        }
    }

//  A1/D1
    if( addrx >= addr3 ){
    
        if( addrx >= addr3 + 900 + addr_offset ){
            tmp = 0;
        } else {
            int addr_tmp = addr - 1024*3;
            if( addr_tmp < 500 ){
                tmp = code_max * ( pi_2 + atan(slope*(addr_tmp-300)) );
            } else {
                tmp = code_max * ( pi_2 - atan(slope*(addr_tmp-700)) );
            }
        }
    }
    
    code = (uint32_t)(tmp);

/*    code = 0;   // for debug， "冻住行转移驱动"*/
    
    return code;
}

/*
    @2022年9月6日： 5、6两天的平场图像中出现了不少随机的“亮行”，经过排查（借助ILA抓取垂直转移波形）后发现，是上升沿稍微晚于下降沿，
                    调整后的平场图像中那些“亮行”消失了
*/
uint32_t sram_code_arctan_44s( int addr ){

    uint32_t addr_offset = 100*0;
    uint32_t addr0 = 0x000;
    uint32_t addr1 = 0x400;
    uint32_t addr2 = 0x800;
    uint32_t addr3 = 0xc00;
    
    uint32_t code;
/*    uint32_t code_max = 600;*/
    uint32_t code_max = 575;

    uint32_t code_max_1 = (uint32_t)code_max*0.6;   // A1/D1 or A4/D4
    uint32_t code_max_2 = (uint32_t)code_max*0.6;

    uint32_t code_max_3 = (uint32_t)code_max*0.78;   // A2/D2 or A3/D3
    uint32_t code_max_4 = (uint32_t)code_max*0.78;

    // uint32_t code_max_1 = 550;
    // uint32_t code_max_2 = 500*0;
    // uint32_t code_max_3 = 500*0;
    // uint32_t code_max_4 = 550;

    double slope = 0.5;
    // double slope = 1;       // default
    // double slope = 2;
    double pi = 3.14159;
    double pi_2 = pi/2;
    
    double tmp;
    
    int addrx = addr;

//  对应Img_CLK1
    if( addrx >= addr0 && addr < addr1 ){
    
        if( addrx >= addr0 + 900 + addr_offset ){
            tmp = 0;
        } else {
        
            int addr_tmp = addr;
            if( addr_tmp < 300 ){
                tmp = code_max_4 * ( pi_2 + atan(slope*(addr_tmp-100)) );
            } else {
                tmp = code_max_4 * ( pi_2 - atan(slope*(addr_tmp-475)) );
            }

            tmp += 320;
        }
    }

//  对应Img_CLK4
    if( addrx >= addr1 && addr < addr2 ) {
        
        if( addrx >= addr1 + 900 + addr_offset ){
            tmp = 0;
        } else {
            int addr_tmp = addr - 1024;
            if( addr_tmp < 500 ){
                // tmp = code_max_3 * ( pi_2 + atan(slope*(addr_tmp-300)) );
                tmp = code_max_3 * ( pi_2 + atan(slope*(addr_tmp-325)) );
            } else {
                // tmp = code_max_3 * ( pi_2 - atan(slope*(addr_tmp-700)) );
                tmp = code_max_3 * ( pi_2 - atan(slope*(addr_tmp-675)) );
            }

            tmp += 320;
        }
    }


//  对应Img_CLK3
    if( addrx >= addr2 && addr < addr3 ) {
    
        if( addrx >= addr2 + 900 + addr_offset ){
            tmp = 0;
        } else {
            int addr_tmp = addr - 1024*2;
            if( addr_tmp < 300 ){
                // tmp = code_max_2 * ( pi_2 + atan(slope*(addr_tmp-100)) );
                tmp = code_max_2 * ( pi_2 + atan(slope*(addr_tmp-75)) );
            } else {
                tmp = code_max_2 * ( pi_2 - atan(slope*(addr_tmp-500)) );
                // tmp = code_max_2 * ( pi_2 - atan(slope*(addr_tmp-475)) );
            }

            tmp += 50;  //  微调后A1/D1,A4/D4的输出与AD9106空闲时的输出基本一致
        }
    }

//  对应Img_CLK2
    if( addrx >= addr3 ){
    
        if( addrx >= addr3 + 900 + addr_offset ){
            tmp = 0;
        } else {
            int addr_tmp = addr - 1024*3;
            if( addr_tmp < 500 ){
                tmp = code_max_1 * ( pi_2 + atan(slope*(addr_tmp-300)) );
            } else {
                tmp = code_max_1 * ( pi_2 - atan(slope*(addr_tmp-700)) );
            }

            tmp += 50;  //  微调后A1/D1,A4/D4的输出与AD9106空闲时的输出基本一致
        }
    }
    
    code = (uint32_t)(tmp);

/*    code = 0;   // for debug， "冻住行转移驱动"*/
    
    return code;
}

uint32_t sram_code_exp( int addr ){

    uint32_t addr0 = 0x000;
    uint32_t addr1 = 0x400;
    uint32_t addr2 = 0x800;
    uint32_t addr3 = 0xc00;
    
    uint32_t code;
    uint32_t code_max = 600;

    double slope = 0.1; // default
    // double slope = 1;
    double pi = 3.14;
    double pi_2 = pi/2;
    
    double tmp;
    

//  A4/D4
    if( addr >= addr0 && addr < addr1 ){
    
        if( addr >= addr0 + 900 ){
            tmp = 0;
        } else {
            if( addr < 300 ){
                tmp = pi_2*code_max * ( 1 - 1./(1.+exp(slope*(addr-100))) );
            } else {
                tmp = pi_2*code_max * ( 0 + 1./(1.+exp(slope*(addr-500))) );
            }
        }
    }

//  A3/D3
    if( addr >= addr1 && addr < addr2 ) {
        
        if( addr >= addr1 + 900 ){
            tmp = 0;
        } else {
            int addr_tmp = addr - 1024;
            if( addr_tmp < 500 ){
                tmp = pi_2*code_max * ( 1 - 1./(1.+exp(slope*(addr_tmp-300))) );
            } else {
                tmp = pi_2*code_max * ( 0 + 1./(1.+exp(slope*(addr_tmp-700))) );
            }
        }
    }


//  A2/D2
    if( addr >= addr2 && addr < addr3 ) {
    
        if( addr >= addr2 + 900 ){
            tmp = 0;
        } else {
            int addr_tmp = addr - 1024*2;
            if( addr_tmp < 300 ){
                tmp = pi_2*code_max * ( 1 - 1./(1.+exp(slope*(addr_tmp-100))) );
            } else {
                tmp = pi_2*code_max * ( 0 + 1./(1.+exp(slope*(addr_tmp-500))) );
            }
        }
    }

//  A1/D1
    if( addr >= addr3 ){
    
        if( addr >= addr3 + 900 ){
            tmp = 0;
        } else {
            int addr_tmp = addr - 1024*3;
            if( addr_tmp < 500 ){
                tmp = pi_2*code_max * ( 1 - 1./(1.+exp(slope*(addr_tmp-300))) );
            } else {
                tmp = pi_2*code_max * ( 0 + 1./(1.+exp(slope*(addr_tmp-700))) );
            }
        }
    }
    
    code = (uint32_t)(tmp*2);
    
    return code;
}


